/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CASCADE_H__
#define __CASCADE_H__

#include "EvolutiveLib.h"
#include "ClassEnsemble.h"
#include "AdaBoost.h"
#include "SamplesSet.h"
#include <fstream>

namespace Evolutive {

	//! Define the type of threshold modes.
	enum EVOLUTIVELIB_API THR_FIND_MODE {THRF_MIN_ERROR,THRF_HR,THRF_MIN_WERROR,THRF_MIN_BERR};

	//! Class that codifies an ensemble of classifiers with a cascade architecture
	class EVOLUTIVELIB_API CCascade : public CClassEnsemble
	{
		//! Methods
	public:
		//! Default constructor		
		CCascade(void);

		//! Default destructor
		virtual ~CCascade(void);

#ifdef USE_OPENCV
		//! Returns the class name (From base class)
		virtual string GetClassNameID(void) {return "CCascade";}

		//! Classify a given data (From base class)
		virtual double Apply(CData *InputData);

		//! Save or recover the data to/from a file (from base class)
		virtual void Serialize(std::fstream &fs,bool Saving);

		//! Returns the threshold value for a certain stage
		double GetStageThr(int Idx);

		//! Set the threshold value for a cenrtain classifier
		void SetStageThr(int Idx,double Thr);

		//! Add a new classifier to the ensemble (overload from base class)
		void AddClassifier(CClassifier *Classifier);

		//! Redefinition to allows the addition of a threshold
		void AddClassifier(CClassifier *Classifier,double Threshold);

		//! Find the best value to divide a set of data
		double FindThreshold(int NumVals,double *Values, int *Labels,THR_FIND_MODE Mode,double *ParW_HR=NULL,double *FA=NULL);

		//! Learn a cascade using a given weak learner
		void Train(double MinHR,double MaxFA,double MaxStages,CABWeakLearner *WeakLearner,CSamplesSet *SampleSet,string OutFile);

	protected:

#endif //USE_OPENCV

		//! Attributes
	protected:			

		//! Evaluate the performance of the cascade
		void GetErrors(double &HR,double &FA,int NumSamples,double *Values,int *Labels,double Threshold);
		
		//! Thresholds applied to each stage
		CDblVector m_StageThresholds;

	};	
}

#endif // __CASCADE_H__
